import { type BrowserWindow, dialog, ipcMain } from "electron";

export const { registerDialogInvoker } = (() => {
  const winds = new Map<number, BrowserWindow>();

  function registerDialogInvoker(wind: BrowserWindow) {
    winds.set(wind.webContents.id, wind);
    wind.once("close", () => winds.delete(wind.webContents.id));
  }

  ipcMain.handle("dialog.show-open", showDialogFn(showOpenDialog));
  ipcMain.handle("dialog.show-save", showDialogFn(showSaveDialog));

  ipcMain.handle("dialog.show-message", showDialogFn(showMessageBox));
  ipcMain.on("dialog.show-error", showErrorBox);

  function showDialogFn(listener: (wind: BrowserWindow | undefined, ...args: any[]) => Promise<any>) {
    return (event: Electron.IpcMainInvokeEvent, ...args: any[]) => {
      const wind = winds.get(event.sender.id);
      return listener(wind, ...args);
    };
  }

  function showOpenDialog(wind: BrowserWindow | undefined, options: Electron.OpenDialogOptions): Promise<Electron.OpenDialogReturnValue> {
    return wind == null ? dialog.showOpenDialog(options) : dialog.showOpenDialog(wind, options);
  }

  function showSaveDialog(wind: BrowserWindow | undefined, options: Electron.SaveDialogOptions): Promise<Electron.SaveDialogReturnValue> {
    return wind == null ? dialog.showSaveDialog(options) : dialog.showSaveDialog(wind, options);
  }

  function showMessageBox(wind: BrowserWindow | undefined, options: Electron.MessageBoxOptions) {
    return wind == null ? dialog.showMessageBox(options) : dialog.showMessageBox(wind, options);
  }

  function showErrorBox(_: Electron.IpcMainEvent, title: string, content: string) {
    dialog.showErrorBox(title, content);
  }

  return {
    registerDialogInvoker: registerDialogInvoker,
  };
})();
